package IC.asm.operands;

import IC.asm.LoweringContext;
import IC.asm.Visitor;


/**
 * Memory operand
 */
public class MemOperand extends Operand 
implements LoweringContext {
	/**
	 * offset(base, index, scale)
	 * 
	 * base+index*scale+offset
	 */
	private RegOperand 		base, index;
	private int 			offset, scale;

	/**
	 * @param base
	 * @param index
	 * @param offset
	 * @param scale
	 */
	public MemOperand(RegOperand base, int offset, 
			RegOperand index, int scale) {
		assert(base != null);
		assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
		this.base = base;
		this.index = index;
		this.offset = offset;
		this.scale = scale;
	}

	public MemOperand(RegOperand base, int offset, 
			RegOperand index) {
		assert(base != null);
		this.base = base;
		this.index = index;
		this.offset = offset;
		this.scale = 1;
	}

	public MemOperand(RegOperand base, int offset) {
		assert(base != null);
		this.base = base;
		this.offset = offset;
		this.index = null;
		this.scale = 1;
	}
	
	public MemOperand(RegOperand base) {
		assert(base != null);
		this.base = base;
		this.offset = 0;
		this.index = null;
		this.scale = 1;
	}
	
	/**
	 * @return the base
	 */
	public RegOperand getBase() {
		return base;
	}

	/**
	 * @return the index
	 */
	public RegOperand getIndex() {
		return index;
	}

	/**
	 * @return the offset
	 */
	public int getOffset() {
		return offset;
	}

	/**
	 * @return the scale
	 */
	public int getScale() {
		return scale;
	}

	@Override
	public <D, U> U accept(Visitor<D, U> v, D d) {
		return v.visit(this, d);
	}

	public ContextKind getKind() {
		return ContextKind.Mem;
	}

	@Override
	public boolean equals(Object o)
	{
		if (! (o instanceof MemOperand) )
			return false;
		MemOperand m = (MemOperand)o;
		return m.base.equals(base)
				&& (m.offset == offset)
				&& (m.scale == scale)
				&& ( (index == null && m.index==null) 
					|| m.index.equals(index));
	}

	public void Remove() {}

	public void SetLast() {}
}
